<template>
    <div class="ocr-container">
        <!-- 主内容区域 -->
        <div class="main-content">
            <!-- 上传和预览区域 -->
            <div class="upload-preview-section">
                <!-- 上传区域 -->
                <div class="upload-section">
                    <el-upload class="upload-area" action="" :auto-upload="false" :on-change="handleFileSelect"
                        :before-upload="beforeUploadCheck" :show-file-list="false" accept="image/*" :drag="true"
                        @drop.native.prevent="handleDrop" @dragover.native.prevent="handleDragOver"
                        @dragleave.native="handleDragLeave">
                        <div class="upload-box" :class="{ 'drag-over': isDragOver }">
                            <!-- <UploadFilled class="upload-icon" /> -->
                            <div class="upload-text">
                                <p class="main-text">点击或拖拽图片到此处上传</p>
                                <p class="sub-text">支持JPG、PNG、BMP格式，大小不超过10MB</p>
                            </div>
                        </div>
                    </el-upload>

                    <!-- 文件信息和操作 -->
                    <div class="file-info-actions" v-if="selectedFileName">
                        <div class="selected-file">
                            <!-- <Document class="file-icon" /> -->
                            <div class="file-details">
                                <span class="filename">{{ selectedFileName }}</span>
                                <span class="file-size">{{ formatFileSize(selectedFile?.size) }}</span>
                            </div>
                            <div class="file-actions">
                                <el-button type="danger" text @click="clearFile" size="small" circle>
                                    <Close />
                                </el-button>
                                <el-button type="primary" @click="startRecognition" :loading="isProcessing"
                                    size="small">
                                    {{ isProcessing ? '识别中...' : '开始识别' }}
                                </el-button>
                            </div>
                        </div>
                    </div>

                    <!-- 图片预览 -->
                    <div class="image-preview-wrapper" v-if="imagePreviewUrl">
                        <div class="preview-header">
                            <span>图片预览</span>
                            <el-tooltip content="放大预览" placement="top">
                                <el-button text @click="openPreviewDialog" size="small" circle>
                                    <ZoomIn />
                                </el-button>
                            </el-tooltip>
                        </div>
                        <div class="image-preview">
                            <el-image :src="imagePreviewUrl" alt="图片预览" fit="contain"
                                :preview-src-list="[imagePreviewUrl]" :preview-teleported="true" hide-on-click-modal>
                                <template #error>
                                    <div class="image-error">
                                        <!-- <Picture class="error-icon" /> -->
                                        <span>图片加载失败</span>
                                    </div>
                                </template>
                            </el-image>
                        </div>
                    </div>
                </div>

                <!-- 结果展示区域 -->
                <div class="result-section" v-if="ocrResult">
                    <div class="result-header">
                        <h2>识别结果</h2>
                        <div class="result-actions">
                            <el-tooltip content="复制文本" placement="top">
                                <el-button type="success" @click="copyToClipboard" size="small" circle>
                                    <CopyDocument />
                                </el-button>
                            </el-tooltip>
                            <el-tooltip content="导出为TXT" placement="top">
                                <el-button type="info" @click="exportAsTxt" size="small" circle>
                                    <Download />
                                </el-button>
                            </el-tooltip>
                            <el-tooltip content="导出为Word" placement="top">
                                <el-button type="primary" @click="exportAsDocx" size="small" circle
                                    :loading="isProcessing">
                                    <Document />
                                </el-button>
                            </el-tooltip>
                            <el-tooltip content="清空结果" placement="top">
                                <el-button type="danger" @click="clearResult" size="small" circle>
                                    <Delete />
                                </el-button>
                            </el-tooltip>
                        </div>
                    </div>
                    <div class="result-content">
                        <pre v-if="isTextContent">{{ ocrResult }}</pre>
                        <div v-else v-html="formatOcrResult(ocrResult)"></div>
                    </div>
                </div>

                <!-- 历史记录区域 -->
                <div class="history-section" v-if="historyList.length > 0">
                    <div class="history-header">
                        <h3>识别历史</h3>
                        <div class="history-actions">
                            <el-input v-model="searchQuery" placeholder="搜索历史记录" clearable size="small"
                                style="width: 200px">
                                <template #prefix>
                                    <Search />
                                </template>
                            </el-input>
                            <el-tooltip content="清空历史" placement="top">
                                <el-button type="danger" text @click="clearAllHistory" size="small" circle>
                                    <Delete />
                                </el-button>
                            </el-tooltip>
                        </div>
                    </div>
                    <div class="history-scroll-container">
                        <div class="history-items">
                            <div v-for="(item, index) in filteredHistory" :key="index" class="history-item"
                                :class="{ 'active': activeHistoryIndex === index }"
                                @click="loadHistoryItem(item, index)">
                                <div class="history-item-header">
                                    <!-- <Document class="history-icon" /> -->
                                    <span class="history-filename">{{ item.fileName }}</span>
                                    <el-button type="text" class="history-remove-btn"
                                        @click.stop="removeHistoryItem(index)" size="small" circle>
                                        <Close />
                                    </el-button>
                                </div>
                                <div class="history-meta">
                                    <span class="history-time">{{ formatDate(item.time) }}</span>
                                    <span class="history-size">{{ formatFileSize(item.content.length) }}</span>
                                </div>
                                <div class="history-preview">{{ item.content.substring(0, 80) }}...</div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <!-- 图片预览对话框 -->
            <el-dialog v-model="previewDialogVisible" title="图片预览" width="80%" top="5vh" destroy-on-close>
                <div class="preview-dialog-content">
                    <el-image :src="imagePreviewUrl" fit="contain" style="max-height: 70vh; width: 100%" />
                </div>
            </el-dialog>
        </div>
    </div>
</template>
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue';
import { ElMessage, ElLoading, ElMessageBox } from 'element-plus';
import { UploadFilled, Document, Close, ZoomIn, CopyDocument, Download, Delete, Search, Picture } from '@element-plus/icons-vue';
import { uploadRequest } from '@/Util/request';
import { Document as DocxDocument, Paragraph, TextRun, Packer } from "docx";
import { saveAs } from "file-saver";

interface RecognitionHistory {
    time: Date;
    content: string;
    fileName: string;
    previewUrl: string;
}

// 状态管理
const selectedFile = ref<File | null>(null);
const selectedFileName = ref('');
const imagePreviewUrl = ref('');
const isProcessing = ref(false);
const ocrResult = ref('');
const historyList = ref<RecognitionHistory[]>([]);
const activeHistoryIndex = ref<number | null>(null);
const isDragOver = ref(false);
const searchQuery = ref('');
const previewDialogVisible = ref(false);

// 计算属性
const filteredHistory = computed(() => {
    if (!searchQuery.value) return historyList.value;
    return historyList.value.filter(item =>
        item.fileName.toLowerCase().includes(searchQuery.value.toLowerCase()) ||
        item.content.toLowerCase().includes(searchQuery.value.toLowerCase())
    );
});
// 导出为Word文档
const exportAsDocx = async () => {
    if (!ocrResult.value) return;

    try {
        isProcessing.value = true;
        const doc = new DocxDocument({
            sections: [{
                properties: {},
                children: [
                    new Paragraph({
                        children: [
                            new TextRun({
                                text: "OCR识别结果",
                                bold: true,
                                size: 28,
                            }),
                        ],
                    }),
                    new Paragraph({
                        children: [
                            new TextRun({
                                text: `文件名: ${selectedFileName.value}`,
                                size: 22,
                            }),
                        ],
                    }),
                    new Paragraph({
                        children: [
                            new TextRun({
                                text: `识别时间: ${new Date().toLocaleString()}`,
                                size: 22,
                            }),
                        ],
                    }),
                    new Paragraph({
                        children: [new TextRun("")],
                    }),
                    new Paragraph({
                        children: [
                            new TextRun({
                                text: ocrResult.value,
                                size: 24,
                            }),
                        ],
                    }),
                ],
            }],
        });

        const blob = await Packer.toBlob(doc);
        saveAs(blob, `ocr_result_${new Date().toISOString().slice(0, 10)}.docx`);
        ElMessage.success("Word文档导出成功");
    } catch (error) {
        console.error("导出Word失败:", error);
        ElMessage.error("Word文档导出失败");
    } finally {
        isProcessing.value = false;
    }
};

const isTextContent = computed(() => {
    return ocrResult.value.split('\n').length < 50 &&
        ocrResult.value.length < 1000 &&
        !ocrResult.value.includes('<') &&
        !ocrResult.value.includes('>');
});

// 文件类型验证方法
const beforeUploadCheck = (file: File) => {
    const validTypes = ['image/png', 'image/jpeg', 'image/bmp'];
    const isImage = validTypes.includes(file.type);
    const isJpeg = file.type === 'image/jpeg' &&
        (file.name.toLowerCase().endsWith('.jpg') ||
            file.name.toLowerCase().endsWith('.jpeg'));

    if (!isImage || (file.type === 'image/jpeg' && !isJpeg)) {
        ElMessage.error('仅支持PNG、JPG/JPEG和BMP格式的图片');
        return false;
    }

    if (file.size > 10 * 1024 * 1024) {
        ElMessage.error('图片大小不能超过10MB');
        return false;
    }

    return true;
};

// 格式化文件大小
const formatFileSize = (bytes?: number) => {
    if (!bytes) return '';
    if (bytes < 1024) return bytes + ' B';
    if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
    return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
};

// 拖拽相关处理
const handleDragOver = () => {
    isDragOver.value = true;
};

const handleDragLeave = () => {
    isDragOver.value = false;
};

const handleDrop = (e: DragEvent) => {
    isDragOver.value = false;
    if (e.dataTransfer?.files.length) {
        const file = e.dataTransfer.files[0];
        if (beforeUploadCheck(file)) {
            handleFileSelect({ raw: file, name: file.name });
        }
    }
};

// 格式化OCR结果
const formatOcrResult = (result: string) => {
    if (!result) return '';
    return result
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/\n/g, '<br>')
        .replace(/\r/g, '')
        .replace(/ /g, '&nbsp;');
};

// 处理文件选择
const handleFileSelect = (file: any) => {
    const reader = new FileReader();
    reader.onload = (e) => {
        const img = new Image();
        img.onload = () => {
            if (img.width > 5000 || img.height > 5000) {
                ElMessage.warning('图片尺寸过大，建议缩小后上传');
            }
            selectedFile.value = file.raw;
            selectedFileName.value = file.name;
            ocrResult.value = '';
            imagePreviewUrl.value = URL.createObjectURL(file.raw);
        };
        img.onerror = () => {
            ElMessage.error('图片加载失败，文件可能已损坏');
            clearFile();
        };
        img.src = e.target?.result as string;
    };
    reader.readAsDataURL(file.raw);
};

// 清除已选择文件
const clearFile = () => {
    selectedFile.value = null;
    selectedFileName.value = '';
    if (imagePreviewUrl.value) {
        URL.revokeObjectURL(imagePreviewUrl.value);
        imagePreviewUrl.value = '';
    }
};

// 清除结果
const clearResult = () => {
    ocrResult.value = '';
};

// 开始OCR识别
const startRecognition = async () => {
    if (!selectedFile.value) {
        ElMessage.warning('请先选择图片文件');
        return;
    }

    const formData = new FormData();
    formData.append('file', selectedFile.value);

    try {
        isProcessing.value = true;
        const loading = ElLoading.service({
            lock: true,
            text: '正在识别文字，请稍候...',
            background: 'rgba(0, 0, 0, 0.7)'
        });

        const result = await uploadRequest<string>({
            url: 'medical/extract',
            method: 'post',
            data: formData,
        });

        ocrResult.value = result;
        saveToHistory(selectedFileName.value, result);
        ElMessage.success('识别成功！');
        loading.close();
    } catch (error) {
        console.error('识别失败:', error);
        ElMessage.error('识别失败，请重试');
    } finally {
        isProcessing.value = false;
    }
};

// 复制结果到剪贴板
const copyToClipboard = () => {
    if (!ocrResult.value) return;

    navigator.clipboard.writeText(ocrResult.value)
        .then(() => ElMessage.success('已复制到剪贴板'))
        .catch(() => {
            const textarea = document.createElement('textarea');
            textarea.value = ocrResult.value;
            document.body.appendChild(textarea);
            textarea.select();
            document.execCommand('copy');
            document.body.removeChild(textarea);
            ElMessage.success('已复制到剪贴板');
        });
};

// 导出为TXT文件
const exportAsTxt = () => {
    if (!ocrResult.value) return;

    const blob = new Blob([ocrResult.value], { type: 'text/plain' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `ocr_result_${new Date().toISOString().slice(0, 10)}.txt`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
};

// 保存到历史记录
const saveToHistory = (fileName: string, content: string) => {
    const newRecord: RecognitionHistory = {
        time: new Date(),
        fileName,
        content,
        previewUrl: imagePreviewUrl.value || '',
    };

    historyList.value.unshift(newRecord);
    if (historyList.value.length > 20) historyList.value.pop();

    localStorage.setItem('ocrHistory', JSON.stringify(
        historyList.value.map(item => ({
            ...item,
            time: item.time.toISOString()
        }))
    ));
};

// 加载历史记录项
const loadHistoryItem = (item: RecognitionHistory, index: number) => {
    activeHistoryIndex.value = index;
    ocrResult.value = item.content;
    selectedFileName.value = item.fileName;
    imagePreviewUrl.value = item.previewUrl;
};

// 删除历史记录项
const removeHistoryItem = async (index: number) => {
    try {
        await ElMessageBox.confirm('确定要删除这条历史记录吗?', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
        });

        historyList.value.splice(index, 1);
        localStorage.setItem('ocrHistory', JSON.stringify(
            historyList.value.map(item => ({
                ...item,
                time: item.time.toISOString()
            }))
        ));

        if (activeHistoryIndex.value === index) {
            activeHistoryIndex.value = null;
            ocrResult.value = '';
            selectedFileName.value = '';
            imagePreviewUrl.value = '';
        }

        ElMessage.success('历史记录已删除');
    } catch {
        // 用户取消删除
    }
};

// 清空所有历史记录
const clearAllHistory = async () => {
    try {
        await ElMessageBox.confirm('确定要清空所有历史记录吗?', '警告', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
        });

        historyList.value = [];
        localStorage.removeItem('ocrHistory');
        activeHistoryIndex.value = null;
        ElMessage.success('所有历史记录已清空');
    } catch {
        // 用户取消清空
    }
};

// 打开预览对话框
const openPreviewDialog = () => {
    previewDialogVisible.value = true;
};

// 格式化日期时间
const formatDate = (date: Date): string => {
    return new Intl.DateTimeFormat('zh-CN', {
        year: 'numeric',
        month: '2-digit',
        day: '2-digit',
        hour: '2-digit',
        minute: '2-digit',
    }).format(date);
};

// 初始化加载历史记录
onMounted(() => {
    try {
        const savedHistory = localStorage.getItem('ocrHistory');
        if (savedHistory) {
            const parsedHistory = JSON.parse(savedHistory) as any[];
            historyList.value = parsedHistory.map(item => ({
                ...item,
                time: new Date(item.time)
            }));
        }
    } catch (error) {
        console.error('加载历史记录失败:', error);
        localStorage.removeItem('ocrHistory');
    }
});
</script>

<style>
.ocr-container {
    /* max-width: 1000px; */
    margin: 0 auto;
    padding: 20px;
    color: #333;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

/* 应用标题 */
.app-header {
    text-align: center;
    margin: 20px 0 40px;
    padding-bottom: 20px;
    border-bottom: 1px solid #eee;
}

.app-header h1 {
    color: #303133;
    margin-bottom: 10px;
    font-size: 28px;
    font-weight: 500;
    background: linear-gradient(90deg, #409EFF, #67C23A);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

.app-header .slogan {
    color: #909399;
    font-size: 16px;
}

.main-content {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 30px;
}

.upload-preview-section {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

/* 上传区域 */
.upload-section {
    display: flex;
    flex-direction: column;
    gap: 15px;
}

.upload-area {
    width: 100%;
}

.upload-box {
    border: 2px dashed #c0c4cc;
    border-radius: 8px;
    padding: 40px 20px;
    text-align: center;
    transition: all 0.3s;
    cursor: pointer;
    background-color: #fafafa;
}

.upload-box.drag-over {
    border-color: #409EFF;
    background-color: #f0f7ff;
}

.upload-box .upload-icon {
    font-size: 48px;
    color: #c0c4cc;
    margin-bottom: 20px;
}

.upload-box .upload-text .main-text {
    font-size: 18px;
    color: #303133;
    margin-bottom: 8px;
    font-weight: 500;
}

.upload-box .upload-text .sub-text {
    font-size: 14px;
    color: #909399;
}

/* 文件信息和操作 */
.file-info-actions .selected-file {
    display: flex;
    align-items: center;
    padding: 12px 15px;
    background-color: #f5f7fa;
    border-radius: 8px;
    border: 1px solid #e4e7ed;
    gap: 12px;
}

.file-info-actions .selected-file .file-icon {
    color: #409EFF;
    font-size: 20px;
}

.file-info-actions .selected-file .file-details {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.file-info-actions .selected-file .file-details .filename {
    font-size: 14px;
    color: #303133;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.file-info-actions .selected-file .file-details .file-size {
    font-size: 12px;
    color: #909399;
}

.file-info-actions .selected-file .file-actions {
    display: flex;
    gap: 8px;
}

/* 图片预览 */
.image-preview-wrapper .preview-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 10px;
}

.image-preview-wrapper .preview-header span {
    font-size: 14px;
    color: #606266;
}

.image-preview-wrapper .image-preview {
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid #e4e7ed;
}

.image-preview-wrapper .image-preview .el-image {
    width: 100%;
    height: 300px;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: #f5f5f5;
}

.image-preview-wrapper .image-preview .el-image .image-error {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    color: #f56c6c;
}

.image-preview-wrapper .image-preview .el-image .image-error .error-icon {
    font-size: 48px;
    margin-bottom: 10px;
}

/* 结果展示区域 */
.result-section {
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid #e4e7ed;
}

.result-section .result-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 15px 20px;
    background-color: #f5f7fa;
    border-bottom: 1px solid #e4e7ed;
}

.result-section .result-header h2 {
    margin: 0;
    font-size: 16px;
    color: #303133;
    font-weight: 500;
}

.result-section .result-header .result-actions {
    display: flex;
    gap: 8px;
}

.result-section .result-content {
    padding: 20px;
    max-height: 400px;
    overflow-y: auto;
    background-color: #f8f8f8;
}

.result-section .result-content pre {
    margin: 0;
    white-space: pre-wrap;
    font-family: 'Menlo', 'Monaco', 'Consolas', monospace;
    line-height: 1.6;
    color: #333;
}

.result-section .result-content div {
    line-height: 1.6;
    font-family: 'Menlo', 'Monaco', 'Consolas', monospace;
}

/* 历史记录区域 */
.history-section {
    border-radius: 8px;
    border: 1px solid #e4e7ed;
    padding: 20px;
    background-color: #fff;
}

.history-section .history-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 15px;
}

.history-section .history-header h3 {
    margin: 0;
    font-size: 16px;
    color: #303133;
    font-weight: 500;
}

.history-section .history-header .history-actions {
    display: flex;
    align-items: center;
    gap: 10px;
}

.history-section .history-scroll-container {
    max-height:1274px;
    overflow-y: auto;
    padding-right: 8px;
}

/* 滚动条样式 */
.history-section .history-scroll-container::-webkit-scrollbar {
    width: 6px;
}

.history-section .history-scroll-container::-webkit-scrollbar-track {
    background: #f1f1f1;
    border-radius: 3px;
}

.history-section .history-scroll-container::-webkit-scrollbar-thumb {
    background: #c1c1c1;
    border-radius: 3px;
}

.history-section .history-scroll-container::-webkit-scrollbar-thumb:hover {
    background: #a8a8a8;
}

.history-section .history-items {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.history-section .history-item {
    padding: 12px;
    border-radius: 6px;
    border: 1px solid #e4e7ed;
    cursor: pointer;
    transition: all 0.2s;
    background-color: #fafafa;
}

.history-section .history-item:hover {
    background-color: #f5f7fa;
    border-color: #d3d6d8;
}

.history-section .history-item.active {
    background-color: #f0f7ff;
    border-color: #c6e2ff;
}

.history-section .history-item .history-item-header {
    display: flex;
    align-items: center;
    margin-bottom: 6px;
}

.history-section .history-item .history-item-header .history-icon {
    color: #909399;
    margin-right: 8px;
    font-size: 16px;
}

.history-section .history-item .history-item-header .history-filename {
    flex: 1;
    font-size: 14px;
    color: #303133;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.history-section .history-item .history-item-header .history-remove-btn {
    color: #909399;
    margin-left: 8px;
}

.history-section .history-item .history-meta {
    display: flex;
    justify-content: space-between;
    margin-bottom: 6px;
    font-size: 12px;
    color: #909399;
}

.history-section .history-item .history-preview {
    font-size: 13px;
    color: #606266;
    line-height: 1.5;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* 响应式适配 */
@media (max-width: 768px) {
    .ocr-container {
        padding: 15px;
    }

    .app-header h1 {
        font-size: 24px;
    }

    .upload-box {
        padding: 30px 15px;
    }

    .selected-file {
        flex-wrap: wrap;
    }

    .selected-file .file-details {
        min-width: 0;
    }

    .selected-file .file-actions {
        width: 100%;
        justify-content: flex-end;
    }

    .image-preview .el-image {
        height: 250px;
    }

    .result-content {
        padding: 15px;
        max-height: 300px;
    }

    .history-section {
        padding: 15px;
    }

    .history-header {
        flex-direction: column;
        align-items: flex-start !important;
        gap: 10px;
    }

    .history-header .history-actions {
        width: 100%;
    }
}
</style>